import re

from django.conf import settings
from django.core.mail import send_mail
from rest_framework import serializers
from users.models import User
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from celery_tasks.email.tasks import send_email


class UserSerializer(serializers.ModelSerializer):
    # 显示指明模型类没有的字段
    password2 = serializers.CharField(max_length=20, min_length=8, write_only=True)
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
    allow = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ('username', 'mobile', 'password', 'password2', 'sms_code', 'allow', 'id', 'token')
        # 额外参数添加
        extra_kwargs = {
            'password': {
                'write_only': True,
                'max_length': 20,
                'min_length': 8,
            },
            'username': {
                'max_length': 20,
                'min_length': 5,
            }
        }

    # 验证手机号格式
    def validate_mobile(self, value):

        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确')

        return value

    # 验证协议
    def validate_allow(self, value):
        if value != 'true':
            raise serializers.ValidationError('未同意协议')
        return value

    # 验证密码和短信验证码
    def validate(self, attrs):

        # 密码验证
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError('密码不一致')

        # 短信验证
        # 1、获取reids中真实短信
        conn = get_redis_connection('sms_codes')
        rel_sms_code = conn.get('sms_code_%s' % attrs['mobile'])
        # 2、判断短信是否超过有效期
        if not rel_sms_code:
            raise serializers.ValidationError('短信验证码失效')
        # 3、比对用户输入的短信和redis中真实短信
        if attrs['sms_code'] != rel_sms_code.decode():
            raise serializers.ValidationError('短信验证不一致')

        return attrs

    # 保存用户数据
    def create(self, validated_data):

        # 1、删除验证后的无用数据
        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']

        # 2、使用模型类保存
        user = User.objects.create_user(**validated_data)

        # 生成加密后的token数据
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER      # 生成载荷部分
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER        # 生成token

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token

        # 3、将保存后的数据对象返回
        return user


class UserDetailSerializer(serializers.ModelSerializer):

    class Meta:

        model = User
        exclude = ('password', )

class UserUpdateSerializer(serializers.ModelSerializer):

    class Meta:

        model = User
        fields = ('email', )

    def update(self, instance, validated_data):

        """更新邮箱"""
        instance.email = validated_data['email']
        instance.save()

        # 往用户的邮箱中发送验证
        # send_mail('美多商城验证', '', settings.EMAIL_FROM, [validated_data['email']], html_message='美多商城邮箱验证<a href="http://www.baidu.com">百度</a>')
        tjs = TJS(settings.SECRET_KEY, 300)
        token = tjs.dumps({'name': instance.username}).decode()
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=' + token
        subject = "美多商城邮箱验证"
        html_message = '<p>尊敬的用户您好！</p>' \
                       '<p>感谢您使用美多商城。</p>' \
                       '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">%s<a></p>' % ([validated_data['email']], verify_url, verify_url)
        # send_mail(subject, "", settings.EMAIL_FROM, [validated_data['email']], html_message=html_message)
        send_email.delay(subject, validated_data['email'], html_message)

        return instance